/***************************************************************************
 * @version   --> v1.0
 * @date      -->2021-04-18
 * @brief     -->电源管理模块
 *            1.通过串口接收上位机发送的指令，主要控制磁矩板电源、热控板电源、
 *            负载版电源、飞轮板电源的通断，并把当前各块板的电源状态和电量返回
 *              通过串口发送给上位机
 *            2.通过Arduino串口调试时，请输入(1, 1, 1, 1)的数字，顺序打开电源开关
 *@update     -->
 **************************************************************************/

/*Includes --------------------------------------------------------------*/
#include <string.h>      // 使用内存拷贝
#include <SCoop.h>      // 使用 SCoop 线程库

/* Private macro --------------------------------------------------------*/
// 宏开关，可启用 Serial 用于串口调试
// 正式编译的时候务必注释掉
//#define SERIAL_DEBUG

/* Private variables ---------------------------------------------------*/
// 引脚定义
int SW0 = A7;     // 磁矩板电源开关引脚，SWITCH_0
int SW1 = A8;     // 热控板电源开关引脚，SWITCH_1
int SW2 = A9;     // 负载板电源开关引脚，SWITCH_2
int SW3 = A10;    // 飞轮板电源开关引脚，SWITCH_3

// 串口数据缓冲区,单次收数据帧限制在 4 字节以内，分别用0和1表示关闭和打开
// 发数据限制在5字节，前4字节表示各模块开关状态，最后一字节表示电量
// 1代表打开开关，0表示关闭，比如打开所有电源开关，则输入1,1,1,1
uint8_t send_buffer[5];
uint8_t receiver_buffer[4];

// 电池电量记录
volatile uint8_t power_level = 9;
int volt;

// 开关状态记录
volatile bool P0_on = false;
volatile bool P1_on = false;
volatile bool P2_on = false;
volatile bool P3_on = false;


// 通过串口接收上位机的指令
defineTask(ReceiverThread); 
  
void ReceiverThread::setup(){
}

void ReceiverThread::loop(){
  uint8_t i = 0;
  // 串口读取数据
  if(Serial.available()>0){
    delay(20);        // 等待串口数据完全进入缓冲区
  }
  while(Serial.available()>0 && i<4){
    receiver_buffer[i] = Serial.parseInt();
    i++;
  }
  
  // 磁矩板电源开关，SWITCH_0
  if(receiver_buffer[0] == 1){
    digitalWrite(SW0, HIGH);
    P0_on = true;
    }
   else{
    digitalWrite(SW0, LOW);
    P0_on = false;
    }
   // 热控板电源开关，SWITCH_1
   if(receiver_buffer[1] == 1){
    digitalWrite(SW1, HIGH);
    P1_on = true;
    }
   else{
    digitalWrite(SW1, LOW);
    P1_on = false;
    }
    // 负载板电源开关，SWITCH_2
   if(receiver_buffer[2] == 1){
    digitalWrite(SW2, HIGH);
    P2_on = true;
    }
   else{
    digitalWrite(SW2, LOW);
    P2_on = false;
    }
    // 飞轮板电源开关，SWITCH_3
   if(receiver_buffer[3] == 1){
    digitalWrite(SW3, HIGH);
    P3_on = true;
    }
   else{
    digitalWrite(SW3, LOW);
    P3_on = false;
    }

#ifdef SERIAL_DEBUG
  Serial.println("此时各模块工作状态：");
  Serial.print("磁矩板电源开关：");
  Serial.println(P0_on);
  Serial.print("热控板电源开关：");
  Serial.println(P1_on);
  Serial.print("负载板电源开关：");
  Serial.println(P2_on);
  Serial.print("飞轮板电源开关：");
  Serial.println(P3_on);
#endif

    sleep(20);
}

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);     // 使用串口通信
  delay(20);
  mySCoop.start();        // 开启线程调度
  // 开关引脚初始化
  pinMode(SW0, OUTPUT);
  pinMode(SW1, OUTPUT);
  pinMode(SW2, OUTPUT);
  pinMode(SW3, OUTPUT);
}

void loop() {
  // put your main code here, to run repeatedly:
  volt = analogRead(29);                      // 读取电量引脚的模拟值，原理图为29脚
  power_level = map(volt, 0, 1023, 0, 10);    // 将读的数据映射到0-10的int
  
#ifdef SERIAL_DEBUG
  Serial.print("此时电池电量：");
  Serial.println(power_level);
#endif


  // 通过串口和上位机通信，返回此时开关状态
  send_buffer[0] = P0_on;
  send_buffer[1] = P1_on;
  send_buffer[2] = P2_on;
  send_buffer[3] = P3_on;
  send_buffer[4] = power_level;
  Serial.write(send_buffer, 5);
  sleep(25);

  yield();    // 让给另一个线程
}
